package fr.vahren.sriksal.controller.impl;

import com.opensymphony.xwork2.ActionSupport;

import fr.vahren.sriksal.business.exception.InternalErrorException;
import fr.vahren.sriksal.business.ITaskProgressBusiness;
import fr.vahren.sriksal.controller.IGenerationController;
import fr.vahren.sriksal.generation.Generator;

public class GenerationController extends ActionSupport implements
		IGenerationController {

	private static final int TIMEOUT = 600;
	private static final int TASK_COMPLETE = 100;
	private ITaskProgressBusiness taskProgressBusiness;

	/**
	 * @param taskProgressBusiness
	 *            the taskProgressBusiness to set
	 */
	public void setTaskProgressBusiness(
			ITaskProgressBusiness taskProgressBusiness) {
		this.taskProgressBusiness = taskProgressBusiness;
	}

	/* REQUEST PARAMETERS FILLED BY STRUTS */
	private String taskName;
	private int step;
	private Runnable generationThread;

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.vahren.sriksal.controller.impl.IGenerationController#generate()
	 */
	@Override
	public String generate() {
		if (taskName == null) {
			LOG.error("taskName missing! ", taskName);
			return ERROR;
		}

		// launch generation thread!
		generationThread = new Runnable() {

			@Override
			public void run() {
				try {
					// Create new progress task
					taskProgressBusiness.createTaskProgress(taskName);

					Generator generator = new Generator();
					synchronized (this) {
						// do first task
						generator.erode();
						taskProgressBusiness.updateProgress(taskName, 1);
						// wake up!
						this.notifyAll();

						// do second task
						generator.generateRivers();
						taskProgressBusiness.updateProgress(taskName, 2);
						// wake up!
						this.notifyAll();

						// do third task
						generator.generateBiomes();
						taskProgressBusiness.updateProgress(taskName, 3);
						// wake up!
						this.notifyAll();

						// do last task
						generator.exportMaps("static/images/map1.bmp");
						taskProgressBusiness.updateProgress(taskName,
								TASK_COMPLETE);
						// wake up!
						this.notifyAll();

					}
				} catch (InternalErrorException e) {
					LOG.error("ERROR!!", "");
					e.printStackTrace();
				}

			}
		};
		// GO!
		new Thread(generationThread).start();

		return SUCCESS;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.vahren.sriksal.controller.impl.IGenerationController#check()
	 */
	@Override
	public String check() {
		if (taskName == null) {
			LOG.error("taskName missing! ", taskName);
			return ERROR;
		}

		// wait untill thread is lauched
		while (generationThread == null)
			;

		synchronized (generationThread) {
			try {
				int timeOut = 0;
				while (taskProgressBusiness.getProgress(taskName) < step
						&& timeOut < TIMEOUT) {
					wait();
					timeOut++;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (InternalErrorException e) {
				LOG.error("ERROR while check!", "");
				e.printStackTrace();
			}
		}
		return SUCCESS;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.vahren.sriksal.controller.impl.IGenerationController#execute()
	 */
	@Override
	public String execute() throws Exception {
		return super.execute();
	}

	/**
	 * @return the taskName
	 */
	public String getTaskName() {
		return taskName;
	}

	/**
	 * @param taskName
	 *            the taskName to set
	 */
	public void setTaskName(String taskName) {
		this.taskName = taskName;
	}

	/**
	 * @return the step
	 */
	public int getStep() {
		return step;
	}

	/**
	 * @param step
	 *            the step to set
	 */
	public void setStep(int step) {
		this.step = step;
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 2485855813134698987L;

}
